﻿Imports System.Reflection

''' <summary>
''' バージョンキー属性
''' </summary>
''' <remarks>
''' 楽観的排他制御処理用の属性
''' </remarks>
<AttributeUsage(AttributeTargets.Class Or AttributeTargets.Property, Allowmultiple:=False)>
Public NotInheritable Class VersionKeyAttribute
    Inherits SpecialValueAttribute

    ''' <summary>
    ''' 保存値が読み込まれるときに発生するイベント
    ''' </summary>
    ''' <remarks></remarks>
    Public Shared Event OnSaveValueReading As EventHandler(Of SaveValueReadingEventArgs)

    ''' <summary>
    ''' バージョンキーかどうかを示します
    ''' </summary>
    ''' <value></value>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Overrides ReadOnly Property IsVersionKey As Boolean
        Get
            Return True
        End Get
    End Property

    ''' <summary>
    ''' 最大バージョン番号を示します
    ''' </summary>
    ''' <value></value>
    ''' <returns></returns>
    ''' <remarks>バージョンを超えるとループします</remarks>
    Public Property MaxVersion As Decimal = 0

    ''' <summary>
    ''' 更新時、書き込み対象とするかどうかを示します
    ''' </summary>
    ''' <value></value>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Overrides Property IsUpdateTrigger As Boolean
        Get
            Return True
        End Get
        Set(value As Boolean)
            Return
        End Set
    End Property

    ''' <summary>
    ''' 値読み込みイベントを発生させます
    ''' </summary>
    ''' <param name="instance"></param>
    ''' <param name="prop"></param>
    ''' <param name="oldValue"></param>
    ''' <remarks></remarks>
    Public Overrides Sub RaiseSaveValueReadingEvent(instance As Object, prop As LiteralProperty, oldValue As Object)
        If instance Is Nothing Then Throw New ArgumentNullException("instance")
        If prop Is Nothing Then Throw New ArgumentNullException("prop")

        'バージョンインクリメント
        Dim newVer As Decimal = 0
        If oldValue IsNot Nothing Then
            newVer = Decimal.Parse(oldValue.ToString)
        End If
        newVer += 1

        '上限判定と代入
        If 1 < Me.MaxVersion AndAlso Me.MaxVersion < newVer Then newVer = 1
        prop.SetLiteralValue(instance, newVer)

        Dim e As New SaveValueReadingEventArgs With {.Instance = instance, .LiteralProperty = prop, .OldValue = oldValue}
        RaiseEvent OnSaveValueReading(Me, e)
    End Sub
End Class
